#include	"Engine.Application.hpp"
#include	"Engine.Utils.hpp"
#include	"Engine.System.hpp"

#include	<csignal>

#if !defined(_WIN32)
#	include		<sys/time.h>
#	include		<sys/resource.h>
#endif

namespace Engine {

	namespace __Private {
		struct Delegate {
			static void	OnSignal(int nSignal) {
				pApp->OnSignal(nSignal);
			}
			static Application * pApp;
		};
	}

	Application * __Private::Delegate::pApp = nullptr;

	Application::Application() : bShouldExit(true), nExitCode(0) {
		if (__Private::Delegate::pApp)
			throw std::runtime_error("There are more than one instance of Application! Please check you code.");
		__Private::Delegate::pApp = this;
	}

	Application::~Application() {}
		
	void Application::Start(int nArgc, char * pArgv[]) {
		if (nArgc > 0) System::Path::Change(System::Path::PurePath(pArgv[0]));

		signal(SIGINT, &__Private::Delegate::OnSignal);
		signal(SIGABRT, &__Private::Delegate::OnSignal);
		signal(SIGFPE, &__Private::Delegate::OnSignal);
		signal(SIGILL, &__Private::Delegate::OnSignal);
		signal(SIGSEGV, &__Private::Delegate::OnSignal);
		signal(SIGTERM, &__Private::Delegate::OnSignal);

	#if !defined(_WIN32)
		/// Generate core dump file after an exception occured.
		struct rlimit iCore;
		::getrlimit(RLIMIT_CORE, &iCore);
		iCore.rlim_cur = iCore.rlim_max;
		::setrlimit(RLIMIT_CORE, &iCore);
	#endif

		if (OnInit(nArgc, pArgv)) {
			bShouldExit = false;
			while (!bShouldExit && OnBreath()) continue;
		}

		OnUnInit();
	}

	void Application::Exit(int nExitCode) {
		this->bShouldExit	= true;
		this->nExitCode		= nExitCode;
	}

}
